home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1994 October / Macformat17.cdr / Shareware City / Developers / MacVogl-alpha1PPC / viewing.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  6KB  |  271 lines

  1. #include "vogl.h"
  2.  
  3. #ifdef    TC
  4.  
  5. extern    double    cos();
  6. extern    double    sin();
  7. extern    double    asin();
  8. extern    double    sqrt();
  9. extern    double    fabs();
  10.  
  11. #else 
  12.  
  13. #include <math.h>
  14.  
  15. #endif
  16.  
  17. /*
  18.  * NOTE: the words hither and yon are used in this file instead of near and far
  19.  * as they are keywords on some PC compilers (groan). Change them back at your 
  20.  * on peril.
  21.  */
  22.  
  23. #define    SQ(a)    ((a)*(a))
  24. #define COT(a)    ((double)(cos((double)(a)) / sin((double)(a))))
  25.  
  26. /*
  27.  * polarview
  28.  *
  29.  * Specify the viewer's position in polar coordinates by giving
  30.  * the distance from the viewpoint to the world origin, 
  31.  * the azimuthal angle in the x-y plane, measured from the y-axis,
  32.  * the incidence angle in the y-z plane, measured from the z-axis,
  33.  * and the twist angle about the line of sight. Note: that unlike
  34.  * in VOGLE we are back to tenths of degrees.
  35.  *
  36.  */
  37. void
  38. polarview(dist, azim, inc, twist)
  39.     Coord    dist;
  40.     Angle    azim, inc, twist;
  41. {
  42.     if (!vdevice.initialised) 
  43.         verror("polarview: vogl not initialised");
  44.  
  45.     translate(0.0, 0.0, -dist);
  46.     rotate(-twist, 'z');
  47.     rotate(-inc, 'x');
  48.     rotate(-azim, 'z');
  49. }
  50.  
  51. /*
  52.  * normallookat
  53.  *
  54.  *    do the standard lookat transformation.
  55.  */
  56. static void
  57. normallookat(vx, vy, vz, px, py, pz)
  58.     double  vx, vy, vz, px, py, pz;
  59.  
  60. {
  61.     double    l2, l3, sintheta, sinphi, costheta, cosphi;
  62.     Matrix    tmp;
  63.  
  64.     l2 = sqrt((double)(SQ((px - vx)) + SQ((pz - vz))));
  65.     l3 = sqrt((double)(SQ((px - vx)) + SQ((py - vy)) + SQ((pz - vz))));
  66.  
  67.     if (l3 != 0.0) {
  68.         sinphi = (vy - py) / l3;
  69.         cosphi = l2 / l3;
  70.  
  71.         /*
  72.          * Rotate about X by phi
  73.          */
  74.         identmatrix(tmp);
  75.         tmp[1][1] = tmp[2][2] = cosphi;
  76.         tmp[1][2] = sinphi;
  77.         tmp[2][1] = -sinphi;
  78.         multmatrix(tmp);
  79.     }
  80.  
  81.     if (l2 != 0.0) {
  82.         sintheta = (px - vx) / l2;
  83.         costheta = (vz - pz) / l2;
  84.  
  85.         /*
  86.          * Rotate about Y by theta
  87.          */
  88.         identmatrix(tmp);
  89.         tmp[0][0] = tmp[2][2] = costheta;
  90.         tmp[0][2] = -sintheta;
  91.         tmp[2][0] = sintheta;
  92.         multmatrix(tmp);
  93.     }
  94. }
  95.  
  96. /*
  97.  * lookat
  98.  *
  99.  * Specify the viewer's position by giving a viewpoint and a 
  100.  * reference point in world coordinates. A twist about the line
  101.  * of sight may also be given.  Note that unlike in VOGLE we are
  102.  * back to tenths of degrees.
  103.  */
  104. void
  105. lookat(vx, vy, vz, px, py, pz, twist)
  106.     Coord  vx, vy, vz, px, py, pz;
  107.     Angle    twist;
  108. {
  109.     if (!vdevice.initialised) 
  110.         verror("lookat: vogl not initialised");
  111.  
  112.     rotate(-twist, 'z');
  113.  
  114.     normallookat(vx, vy, vz, px, py, pz);
  115.  
  116.     translate(-vx, -vy, -vz);
  117. }
  118.  
  119. /*
  120.  * perspective
  121.  *
  122.  * Specify a perspective viewing pyramid in world coordinates by
  123.  * giving a field of view, aspect ratio, and the locations of the 
  124.  * near(hither) and far(yon) clipping planes in the z direction. Note
  125.  * that unlike in VOGLE we are back to tenths of degrees.
  126.  */
  127. void
  128. perspective(ifov, aspect, hither, yon)
  129.     Angle     ifov;
  130.     double    aspect;
  131.     Coord    hither, yon;
  132. {
  133.     Matrix        mat;
  134.     double        fov;
  135.  
  136.     if (!vdevice.initialised)
  137.         verror("perspective: vogl not initialised");
  138.  
  139.     if (aspect == 0.0)
  140.         verror("perspective: can't have zero aspect ratio!");
  141.  
  142.     if ((yon - hither) == 0.0)
  143.         verror("perspective: near clipping plane same as far one.");
  144.  
  145.     if (ifov == 0 || ifov == 1800)
  146.         verror("perspective: bad field of view passed.");
  147.  
  148.     fov = ifov / 10.0;
  149.     identmatrix(mat);
  150.  
  151.     mat[0][0] = COT((D2R * fov / 2.0)) / aspect;
  152.     mat[1][1] = COT((D2R * fov / 2.0));
  153.  
  154.     mat[2][2] = -(yon + hither) / (yon - hither);
  155.     mat[2][3] = -1;
  156.     mat[3][2] = -2.0 * yon * hither / (yon - hither);
  157.     mat[3][3] = 0;
  158.  
  159.     loadmatrix(mat);
  160. }
  161.  
  162. /*
  163.  * window
  164.  *
  165.  * Specify a perspective viewing pyramid in world coordinates by
  166.  * giving a rectangle at the near clipping plane and the location
  167.  * of the far clipping plane.
  168.  *
  169.  */
  170. void
  171. window(left, right, bottom, top, hither, yon)
  172.     Coord     left, right, bottom, top, hither, yon;
  173. {
  174.     Matrix        mat;
  175.  
  176.     if (!vdevice.initialised)
  177.         verror("window: vogl not initialised");
  178.  
  179.     if ((right - left) == 0.0)
  180.         verror("window: left clipping plane same as right one.");
  181.  
  182.     if ((top - bottom) == 0.0)
  183.         verror("window: bottom clipping plane same as top one.");
  184.  
  185.     if ((yon - hither) == 0.0)
  186.         verror("window: near clipping plane same as far one.");
  187.  
  188.     identmatrix(mat);
  189.  
  190.     mat[0][0] = 2.0 * hither / (right - left);
  191.     mat[1][1] = 2.0 * hither / (top - bottom);
  192.     mat[2][0] = (right + left) / (right - left);
  193.     mat[2][1] = (top + bottom) / (top - bottom);
  194.     mat[2][2] = -(yon + hither) / (yon - hither);
  195.     mat[2][3] = -1.0;
  196.     mat[3][2] = -2.0 * yon * hither / (yon - hither);
  197.     mat[3][3] = 0.0;
  198.  
  199.     loadmatrix(mat);
  200. }
  201.  
  202. /*
  203.  * ortho
  204.  *
  205.  * Define a three dimensional viewing box by giving the left,
  206.  * right, bottom and top clipping plane locations and the distances
  207.  * along the line of sight to the near and far clipping planes.
  208.  *
  209.  */
  210. void
  211. ortho(left, right, bottom, top, hither, yon)
  212.     Coord     left, right, bottom, top, hither, yon;
  213. {
  214.     Matrix        mat;
  215.  
  216.     if (!vdevice.initialised)
  217.         verror("ortho: vogl not initialised");
  218.  
  219.     if ((right - left) == 0.0)
  220.         verror("ortho: left clipping plane same as right one.");
  221.  
  222.     if ((top - bottom) == 0.0)
  223.         verror("ortho: bottom clipping plane same as top one.");
  224.  
  225.     if ((yon - hither) == 0.0)
  226.         verror("ortho: near clipping plane same as far one.");
  227.  
  228.     identmatrix(mat);
  229.  
  230.     mat[0][0] = 2.0 / (right - left);
  231.     mat[1][1] = 2.0 / (top - bottom);
  232.     mat[2][2] = -2.0 / (yon - hither);
  233.     mat[3][0] = -(right + left) / (right - left);
  234.     mat[3][1] = -(top + bottom) / (top - bottom);
  235.     mat[3][2] = -(yon + hither) / (yon - hither);
  236.  
  237.     loadmatrix(mat);
  238. }
  239.  
  240. /*
  241.  * ortho2
  242.  *
  243.  * Specify a two dimensional viewing rectangle. 
  244.  *
  245.  */
  246. void
  247. ortho2(left, right, bottom, top)
  248.     Coord    left, right, bottom, top;
  249. {
  250.     Matrix    mat;
  251.  
  252.     if (!vdevice.initialised) 
  253.         verror("ortho2: vogl not initialised");
  254.  
  255.     identmatrix(mat);
  256.  
  257.     if ((right - left) == 0.0)
  258.         verror("ortho2: left clipping plane same as right one.");
  259.  
  260.     if ((top - bottom) == 0.0)
  261.         verror("ortho2: bottom clipping plane same as top one.");
  262.  
  263.     mat[0][0] = 2.0 / (right - left);
  264.     mat[1][1] = 2.0 / (top - bottom);
  265.     mat[2][2] = -1.0;
  266.     mat[3][0] = -(right + left) / (right - left);
  267.     mat[3][1] = -(top + bottom) / (top - bottom);
  268.  
  269.     loadmatrix(mat);
  270. }
  271.